﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Text.RegularExpressions;
using System.IO;
using System.Threading;
using System.Globalization;
namespace Chip8
{
    public partial class frmDebugger : Form
    {
        public frmEmu Mainform; //Holder for link to main form
        public frmDebugger()
        {
            InitializeComponent();
        }
       
       public struct Instruction //Instruction Breakdown
        {
            public ushort raw;
            public ushort opnum;
            public ushort nnn;
            public byte n;
            public byte x;
            public byte y;
            public byte kk;
        }

       public List<Breakpoint> Breakpoints = new List<Breakpoint>(); //List of Active Breakpoings
       public class Breakpoint //Class to hold all current breakpoints & flags
       {
           public string Address;
           public bool Read;
           public bool Write;
           public bool Execute;
           public Breakpoint(string Address, bool Read, bool Write, bool Execute)
           {
               this.Address = Address;
               this.Read = Read;
               this.Write = Write;
               this.Execute = Execute;
           }
       }

       public ushort GetOpcodeMask(ushort instruction)
        {
            ushort mask = 0xF000; 
            byte opcode = (byte)((instruction & 0xF000) >> 12); //shift first 4 bits 12 right to the begginning
           
            switch (opcode) //Test Opcode
            {
                case 0x0:
                    {
                        if (instruction > 0)
                        {
                            if ((instruction & 0xFFF0) == 0x00C0)
                                mask = 0xFFF0;
                            else
                                mask = 0xFFFF;
                        }
                        break;
                    }
                case 0xF:
                case 0xE: mask = 0xF0FF; break;
                case 0x8: mask = 0xF00F; break;
                default: mask = 0xF000; break;
            }
       
            return mask;
        }

        StringBuilder Decoded = new StringBuilder(); //Holds Decoded Instruction
        public void BuildInstructionList(ushort address, byte byte1, byte byte2, bool breakpoint)
        {
            try
            {
                //Build Param List
                List<string> Params = new List<string>();
                Params.Add(address.ToString("X4"));                                                 //Address    0
                Params.Add(byte1.ToString("X2"));                                                   //Byte1      1     
                Params.Add(byte2.ToString("X2"));                                                   //Byte2      2
                Params.Add(Mainform.instr.x.ToString("X"));                                         //X          3
                Params.Add(Mainform.instr.y.ToString("X"));                                         //Y          4
                Params.Add(Mainform.instr.n.ToString());                                            //N          5
                Params.Add(Mainform.instr.nnn.ToString("X4"));                                      //NNN        6
                Params.Add(Mainform.instr.kk.ToString("X2"));                                       //KK         7
                Params.Add(Mainform.MainSystem.AddressRegister.ToString("X4"));                     //Address R  8
                Params.Add((Mainform.MainSystem.AddressRegister + Mainform.instr.x).ToString("X4"));//Addr R Cal 9

                if (this.Visible) //Check to see if form is visible before attempting to build an instruction list
                {
                    Decoded.AppendLine(string.Format("{0}  {1} {2}  ", Params.ToArray()));
                    switch (Mainform.instr.raw & GetOpcodeMask(Mainform.instr.raw))
                    {
                        case 0x00C0: //Scroll Display Down Npx
                            Decoded.AppendLine("SCROLL DOWN {5}PX");
                            break;
                        case 0x00E0: //CLS - Clear the display.
                            Decoded.AppendLine("CLS");
                            break;
                        case 0x00EE: //RET - Decoded = from a subroutine. The interpreter sets the program counter to the address at the top of the stack, then subtracts 1 from the stack pointer.
                            Decoded.AppendLine("RET");
                            break;
                        case 0x00FB: //Scroll Display Right 4px
                            Decoded.AppendLine("SCROLL RIGHT 4PX");
                            break;
                        case 0x00FC: //Scroll Display Left 4px
                            Decoded.AppendLine("SCROLL LEFT 4PX");
                            break;
                        case 0x00FD: //Exit Chip-8 Interpreter
                            Decoded.AppendLine("EXIT");
                            break;
                        case 0x00FE: //Disabled Extended Screen
                            Decoded.AppendLine("DISABLE EXTENDED DISPLAY");
                            break;
                        case 0x00FF: //Enable Extended Screen
                            Decoded.AppendLine("ENABLE EXTENDED DISPLAY");
                            break;
                        case 0x1000: //JP - Jump to location nnn. The interpreter sets the program counter to nnn.
                            Decoded.AppendLine(string.Format("JP {6}", Params.ToArray()));
                            break;
                        case 0x2000: //JSR - Push current PC to stack, and set PC = nnn.         
                            Decoded.AppendLine(string.Format("CALL {6}", Params.ToArray()));
                            break;
                        case 0x3000: //SE - Skip next instruction if Vx = kk. The interpreter compares register Vx to kk, and if they are equal, increments the program counter by 2.
                            Decoded.AppendLine(string.Format("SE V[{3}],{7}", Params.ToArray()));
                            break;
                        case 0x4000: //SNE - Skip next instruction if Vx != kk. The interpreter compares register Vx to kk, and if they are not equal, increments the program counter by 2. 
                            Decoded.AppendLine(string.Format("SNE V[{3}], {7}", Params.ToArray()));
                            break;
                        case 0x5000: //SE - Skip next instruction if Vx = Vy. The interpreter compares register Vx to register Vy, and if they are equal, increments the program counter by 2.
                            Decoded.AppendLine(string.Format("SE V[{3}],V[{4}]", Params.ToArray()));
                            break;
                        case 0x6000: //LD Set Vx = kk. The interpreter puts the value kk into register Vx.
                            Decoded.AppendLine(string.Format("LD V[{3}], {7}", Params.ToArray()));
                            break;
                        case 0x7000: //ADD Set Vx = Vx + kk. Adds the value kk to the value of register Vx, then stores the result in Vx.
                            Decoded.AppendLine(string.Format("ADD V[{3}], {7}", Params.ToArray()));
                            break;
                        case 0x8000: //LD - Set Vx = Vy. Stores the value of register Vy in register Vx.
                            Decoded.AppendLine(string.Format("LD V[{3}], V[{4}]", Params.ToArray()));
                            break;
                        case 0x8001: //OR -Set Vx = Vx OR Vy.
                            Decoded.AppendLine(string.Format("OR V[{3}], V[{4}] | V[{4}]", Params.ToArray()));
                            break;
                        case 0x8002: //AND - Set Vx = Vx AND Vy.
                            Decoded.AppendLine(string.Format("AND V[{3}], V[{4}] & V[{4}]", Params.ToArray()));
                            break;
                        case 0x8003: //XOR - Set Vx = Vx XOR Vy.
                            Decoded.AppendLine(string.Format("XOR V[{3}], V[{4}] ^ V[{4}]", Params.ToArray()));
                            break;
                        case 0x8004: //ADD - Set Vx = Vx + Vy, set VF = carry.
                            Decoded.AppendLine(string.Format("ADD V[{3}], V[{4}]", Params.ToArray()));
                            break;
                        case 0x8005: //SUB - Set Vx = Vx - Vy, set VF = NOT borrow.
                            Decoded.AppendLine(string.Format("SUB V[{3}], V[{4}]", Params.ToArray()));
                            break;
                        case 0x8006: //SHR - Set Vx = Vx SHR 1.
                            Decoded.AppendLine(string.Format("SHR V[{3}] {, V[{4}]}", Params.ToArray()));
                            break;
                        case 0x8007: //SUBN - Set Vx = Vy - Vx, set VF = NOT borrow.
                            Decoded.AppendLine(string.Format("SUBN V[{3}], V[{4}]", Params.ToArray()));
                            break;
                        case 0x800E: //SHL - Set Vx = Vx SHL 1.
                            Decoded.AppendLine(string.Format("SHR V[{3}] {, V[{4}]}", Params.ToArray()));
                            break;
                        case 0x9000: //SNE - Skip next instruction if Vx != Vy.
                            Decoded.AppendLine(string.Format("SNE V[{3}], V[{4}]", Params.ToArray()));
                            break;
                        case 0xA000: //LD - Set I = nnn.
                            Decoded.AppendLine(string.Format("LD I ({8}),{6}", Params.ToArray()));
                            break;
                        case 0xB000: //JMP - Jump to location nnn + V0.
                            Decoded.AppendLine(string.Format("JP V[0], {6}", Params.ToArray()));
                            break;
                        case 0xC000: //RND - Set Vx = random byte AND kk.
                            Decoded.AppendLine(string.Format("RND V[{3}], RND(BYTE) & {7}", Params.ToArray()));
                            break;
                        case 0xD000: //DRW - Draw Screen.
                            if (Mainform.instr.n != 0)
                                Decoded.AppendLine(string.Format("DRW 8 x {5} SPRITE", Params.ToArray()));
                            else
                                Decoded.AppendLine("DRW 16 x 16 SPRITE");
                            break;
                        case 0xE09E: //SKP - Skip next instruction if key with the value of Vx is pressed.
                            Decoded.AppendLine(string.Format("SKP V[{3}]", Params.ToArray()));
                            break;
                        case 0xE0A1: //SKNP - Skip next instruction if key with the value of Vx is not pressed.
                            Decoded.AppendLine(string.Format("SKNP V[{3}]", Params.ToArray()));
                            break;
                        case 0xF007: //LD - Set Vx = delay timer value.
                            Decoded.AppendLine(string.Format("LD V[{3}], DELAY TIMER", Params.ToArray()));
                            break;
                        case 0xF00A: //LD - Wait for a key press, store the value of the key in Vx.
                            Decoded.AppendLine(string.Format("LD V[{3}], {7}", Params.ToArray()));
                            break;
                        case 0xF015: //LD - Set delay timer = Vx.
                            Decoded.AppendLine(string.Format("LD DELAY TIMER, V[{3}]", Params.ToArray()));
                            break;
                        case 0xF018: //LD - Set sound timer = Vx.
                            Decoded.AppendLine(string.Format("LD ST, V[{3}]", Params.ToArray()));
                            break;
                        case 0xF01E: //ADD - Set I = I + Vx.
                            Decoded.AppendLine(string.Format("ADD I ({8}), V[{3}]", Params.ToArray()));
                            break;
                        case 0xF029: //LD - Set I = location of sprite for digit Vx * 5.
                            Decoded.AppendLine(string.Format("LD I ({8}), (V[{3}] * 5)", Params.ToArray()));
                            break;
                        case 0xF030: //LD - Set I = location of sprite for digit Vx * 10 + 80.
                            Decoded.AppendLine(string.Format("LD I ({8}), (V[{3}] * 10) + 80", Params.ToArray()));
                            break;
                        case 0xF033: //LD - Store BCD representation of Vx in memory locations I, I+1, and I+2.
                            Decoded.AppendLine(string.Format("LD B, V[{3}]", Params.ToArray()));
                            break;
                        case 0xF055: //LD - Store registers V0 through Vx in memory starting at location I.
                            Decoded.AppendLine(string.Format("LD " + "[I ({8} - {9})], V[0] - V[{3}] ", Params.ToArray()));
                            break;
                        case 0xF065: //LD - Read registers V0 through Vx from memory starting at location I.
                            Decoded.AppendLine(string.Format("LD " + "V[0] - V[{3}], [I] ({8} - {9})", Params.ToArray()));
                            break;
                        case 0xF075: //LD Store Vx in RPL
                            Decoded.AppendLine(string.Format("LD R, V[{3}]", Params.ToArray()));
                            break;
                        case 0xF085: //LD Store RPL in Vx
                            Decoded.AppendLine(string.Format("LD V[{3}], R", Params.ToArray()));
                            break;
                        default:
                            Decoded.AppendLine("UNKNOWN INSTRUCTION");
                            break;
                    }

                    Decoded.AppendLine(Environment.NewLine);

                    CollectedInctructions.Add(Decoded.ToString());

                    Decoded.Length = 0; //Clear Decoded

                    if (CollectedInctructions.Count > 2000) //Only log the last 2000 instructions
                        CollectedInctructions.RemoveAt(0); //If we exceed 2000 then start removing from the beginning

                    switch (Mainform.instr.raw & GetOpcodeMask(Mainform.instr.raw)) //Test instruction for Read/Write breakpoint
                    {
                        case 0xF055: //Write
                            foreach (Breakpoint BP in Breakpoints)
                            {
                                if (BP.Write)
                                {
                                    for (var i = 0; i <= Mainform.instr.x; i++)
                                    {
                                        if (int.Parse(BP.Address, NumberStyles.HexNumber) == (ushort)(Mainform.MainSystem.AddressRegister + i))
                                        {
                                            Mainform.BreakPoint = true;
                                            break;
                                        }
                                    }
                                }
                            }
                            break;
                        case 0xF065: //Read
                            foreach (Breakpoint BP in Breakpoints)
                            {
                                if (BP.Read)
                                {
                                    for (var i = 0; i <= Mainform.instr.x; i++)
                                    {
                                        if (int.Parse(BP.Address, NumberStyles.HexNumber) == (ushort)(Mainform.MainSystem.AddressRegister + i))
                                        {
                                            Mainform.BreakPoint = true;
                                            break;
                                        }
                                    }
                                }
                            }
                            break;
                    }

                    //Execute
                    foreach (Breakpoint BP in Breakpoints) //Test Breakpoints for Execute
                    {
                        if (BP.Execute)
                        {
                            if (address == int.Parse(BP.Address, NumberStyles.HexNumber))
                            {
                                Mainform.BreakPoint = true;
                                break;
                            }
                        }
                    }

                    if (chkLogCPU.Checked && txtpath.Text != "") //If checked write out log file to path
                    {
                        try
                        {
                            if (chkIncludeRegisters.Checked)
                            {
                                int SpacesNeeded = 40 - Decoded.Length;
                                string Space = "";
                                string VRegisters = " V";

                                for (int i = 0; i < SpacesNeeded; i++)
                                    Space += " ";

                                for (int i = 0; i < Mainform.MainSystem.Vreg.Length; i++)
                                    VRegisters += "[" + i.ToString("X") + "]:" + Mainform.MainSystem.Vreg[i].ToString("X2") + " ";

                                StreamWriter s = new StreamWriter(@txtpath.Text, true);
                                s.WriteLine(Decoded.Replace(Environment.NewLine, "") + Space + "[I]:" + Mainform.MainSystem.AddressRegister.ToString("X4") + VRegisters);
                                s.Close();
                            }
                            else
                            {
                                StreamWriter s = new StreamWriter(@txtpath.Text, true);
                                s.WriteLine(Decoded.Replace(Environment.NewLine, ""));
                                s.Close();
                            }
                        }
                        catch
                        {
                            this.Invoke((MethodInvoker)delegate
                            {
                                chkLogCPU.CheckState = CheckState.Unchecked; //End log write when a breakpoint is hit
                            });
                        }

                        if (Mainform.BreakPoint)
                        {
                            this.Invoke((MethodInvoker)delegate
                            {
                                chkLogCPU.CheckState = CheckState.Unchecked; //End log write when a breakpoint is hit
                            });
                        }
                    }
                }
            }
            catch {; };
        }
    
        private void frmDebugger_FormClosing(object sender, FormClosingEventArgs e)
        {
            e.Cancel = true;
            this.Hide();
        }

        List<string> CollectedInctructions = new List<string>();
        public void UpdateInstructions()
        {
           
           this.Invoke((MethodInvoker)delegate
           {
                lstasm.Items.Clear();
                lstasm.Items.AddRange(CollectedInctructions.ToArray());
                lstasm.SelectedIndex = lstasm.Items.Count - 1;

                lstStack.Items.Clear();
                foreach (object s in Mainform.MainSystem.Stack)
                    lstStack.Items.Add(int.Parse(s.ToString()).ToString("X4"));

               txtV00.Text = Mainform.MainSystem.Vreg[0].ToString();
               txtV01.Text = Mainform.MainSystem.Vreg[1].ToString();
               txtV02.Text = Mainform.MainSystem.Vreg[2].ToString();
               txtV03.Text = Mainform.MainSystem.Vreg[3].ToString();
               txtV04.Text = Mainform.MainSystem.Vreg[4].ToString();
               txtV05.Text = Mainform.MainSystem.Vreg[5].ToString();
               txtV06.Text = Mainform.MainSystem.Vreg[6].ToString();
               txtV07.Text = Mainform.MainSystem.Vreg[7].ToString();
               txtV08.Text = Mainform.MainSystem.Vreg[8].ToString();
               txtV09.Text = Mainform.MainSystem.Vreg[9].ToString();
               txtV0A.Text = Mainform.MainSystem.Vreg[10].ToString();
               txtV0B.Text = Mainform.MainSystem.Vreg[11].ToString();
               txtV0C.Text = Mainform.MainSystem.Vreg[12].ToString();
               txtV0D.Text = Mainform.MainSystem.Vreg[13].ToString();
               txtV0E.Text = Mainform.MainSystem.Vreg[14].ToString();
               txtV0F.Text = Mainform.MainSystem.Vreg[15].ToString();

               txtRLP00.Text = Mainform.MainSystem.regRPL[0].ToString();
               txtRLP01.Text = Mainform.MainSystem.regRPL[1].ToString();
               txtRLP02.Text = Mainform.MainSystem.regRPL[2].ToString();
               txtRLP03.Text = Mainform.MainSystem.regRPL[3].ToString();
               txtRLP04.Text = Mainform.MainSystem.regRPL[4].ToString();
               txtRLP05.Text = Mainform.MainSystem.regRPL[5].ToString();
               txtRLP06.Text = Mainform.MainSystem.regRPL[6].ToString();
               txtRLP07.Text = Mainform.MainSystem.regRPL[7].ToString();
           });
        }

        public void ResetDebugger(bool HardReset = false)
        {
            if (Mainform != null)
            {
                Mainform.BreakPoint = false;
                Mainform.StepInto = false;
                Mainform.StepOver = false;
                Mainform.StepOut = false;
                Mainform.StepOutValue = 0;
            }

            lstasm.Items.Clear();
            lstStack.Items.Clear();


            if (HardReset)
            {
                chkLogCPU.Checked = false;
                txtpath.Text = "";
                foreach (Control c in grpRegisters.Controls)
                {
                    if (c is CheckBox)
                    {
                        CheckBox chk = (CheckBox)c;
                        chk.Checked = false;
                    }

                    if (c is TextBox && c.Tag != null)
                    {
                        if (c.Tag.ToString() == "V")
                            c.Text = "0";
                        else
                            c.Text = "0";
                    }

                }

                foreach (Control c in grpRegistersRPL.Controls)
                {
                    if (c is CheckBox)
                    {
                        CheckBox chk = (CheckBox)c;
                        chk.Checked = false;
                    }

                    if (c is TextBox && c.Tag != null)
                    {
                        if (c.Tag.ToString() == "R")
                            c.Text = "";
                        else
                            c.Text = "0";
                    }
                }
            }
        }

        private void cmdRun_Click(object sender, EventArgs e)
        {
            Mainform.PauseEmulation = false;
            Mainform.BreakPoint = false;
            Mainform.StepInto = false;
            Mainform.StepOver = false;
            Mainform.StepOut = false;
            Mainform.StepOutValue = 0;
            lstasm.Items.Clear();
            lstStack.Items.Clear();
            foreach (Control c in grpRegisters.Controls)
            {
                if (c is TextBox && c.Tag != null)
                {
                        if (c.Tag.ToString() == "V")
                            c.Text = "";
                }
            }
        }

        private void cmdstepinto_Click(object sender, EventArgs e)
        {
            if (Mainform.BreakPoint == false)
                Mainform.BreakPoint = true;
            else
            {
                Mainform.StepInto = true;
                Mainform.StepOver = false;
                Mainform.StepOut = false;
            }
            Mainform.PauseEmulation = false;
        }

        private void cmdStepOut_Click(object sender, EventArgs e)
        {
            if (Mainform.MainSystem.Stack.Count > 0) //Test stack for return addresses
            {
                object[] StackArray = Mainform.MainSystem.Stack.ToArray(); //Convert Stack to Object Array
                Mainform.StepOutValue = ushort.Parse(StackArray[0].ToString()); //Take top of stack as our return address set

                //Cancel other actions
                Mainform.StepOut = true;
                Mainform.BreakPoint = false;
                Mainform.StepInto = false;
                Mainform.StepOver = false;   

                //clear debugger and wait for break to repopulate
                lstasm.Items.Clear();
                lstStack.Items.Clear();
                foreach (Control c in grpRegisters.Controls)
                {
                    if (c is TextBox && c.Tag != null)
                    {
                        if (c.Tag.ToString() == "V")
                            c.Text = "";
                    }
                }

                foreach (Control c in grpRegistersRPL.Controls)
                {
                    if (c is TextBox && c.Tag != null)
                    {
                        if (c.Tag.ToString() == "R")
                            c.Text = "";
                    }
                }
            }
            else
                cmdRun.PerformClick(); //If stack empty then run

            Mainform.PauseEmulation = false;
        }

        public bool IsNumeric(string Val)
        {
            try
            {
                int.Parse(Val);
                return true;
            }
            catch { return false; };
            
        }

        private void cmdAdd_Click(object sender, EventArgs e)
        {
            using (frmBreakpoint frm = new frmBreakpoint())
            {
                frm.ShowDialog();
            }
        }

        private void cmdEdit_Click(object sender, EventArgs e)
        {
            using (frmBreakpoint frm = new frmBreakpoint())
            {
                frm.ShowDialog();
            }
        }

        private void cmdReset_Click(object sender, EventArgs e)
        {
            Mainform.ResetGame();
        }

        private void tmrCheats_Tick(object sender, EventArgs e)
        {
            if (Mainform != null)
            {
                if (!Mainform.StopEmulation)
                {
                    foreach (Control c in grpRegisters.Controls)
                    {
                        if (c is CheckBox)
                        {
                            CheckBox chk = (CheckBox)c;
                            if (chk.Checked)
                            {
                                foreach (Control t in grpRegisters.Controls)
                                {
                                    if (t is TextBox)
                                    {
                                        if (t.Tag.ToString() == chk.Tag && IsNumeric(t.Text))
                                        {
                                            if (int.Parse(t.Text) <= 255)
                                                Mainform.MainSystem.Vreg[int.Parse(chk.Tag.ToString())] = byte.Parse(t.Text);
                                        }
                                    }
                                }
                            }
                        }
                    }

                    foreach (Control c in grpRegistersRPL.Controls)
                    {
                        if (c is CheckBox)
                        {
                            CheckBox chk = (CheckBox)c;
                            if (chk.Checked)
                            {
                                foreach (Control t in grpRegistersRPL.Controls)
                                {
                                    if (t is TextBox)
                                    {
                                        if (t.Tag.ToString() == chk.Tag && IsNumeric(t.Text))
                                        {
                                            if (int.Parse(t.Text) <= 255)
                                                Mainform.MainSystem.regRPL[int.Parse(chk.Tag.ToString())] = byte.Parse(t.Text);
                                        }
                                    }
                                }
                            }
                        }
                    }

                    if (!Mainform.BreakPoint && this.Visible)
                    {
                        if (txtV00.Text != Mainform.MainSystem.Vreg[0].ToString())
                            txtV00.Text = Mainform.MainSystem.Vreg[0].ToString();
                        if (txtV01.Text != Mainform.MainSystem.Vreg[1].ToString())
                            txtV01.Text = Mainform.MainSystem.Vreg[1].ToString();
                        if (txtV02.Text != Mainform.MainSystem.Vreg[2].ToString())
                            txtV02.Text = Mainform.MainSystem.Vreg[2].ToString();
                        if (txtV03.Text != Mainform.MainSystem.Vreg[3].ToString())
                            txtV03.Text = Mainform.MainSystem.Vreg[3].ToString();
                        if (txtV04.Text != Mainform.MainSystem.Vreg[4].ToString())
                            txtV04.Text = Mainform.MainSystem.Vreg[4].ToString();
                        if (txtV05.Text != Mainform.MainSystem.Vreg[5].ToString())
                            txtV05.Text = Mainform.MainSystem.Vreg[5].ToString();
                        if (txtV06.Text != Mainform.MainSystem.Vreg[6].ToString())
                            txtV06.Text = Mainform.MainSystem.Vreg[6].ToString();
                        if (txtV07.Text != Mainform.MainSystem.Vreg[7].ToString())
                            txtV07.Text = Mainform.MainSystem.Vreg[7].ToString();
                        if (txtV08.Text != Mainform.MainSystem.Vreg[8].ToString())
                            txtV08.Text = Mainform.MainSystem.Vreg[8].ToString();
                        if (txtV09.Text != Mainform.MainSystem.Vreg[9].ToString())
                            txtV09.Text = Mainform.MainSystem.Vreg[9].ToString();
                        if (txtV0A.Text != Mainform.MainSystem.Vreg[10].ToString())
                            txtV0A.Text = Mainform.MainSystem.Vreg[10].ToString();
                        if (txtV0B.Text != Mainform.MainSystem.Vreg[11].ToString())
                            txtV0B.Text = Mainform.MainSystem.Vreg[11].ToString();
                        if (txtV0C.Text != Mainform.MainSystem.Vreg[12].ToString())
                            txtV0C.Text = Mainform.MainSystem.Vreg[12].ToString();
                        if (txtV0D.Text != Mainform.MainSystem.Vreg[13].ToString())
                            txtV0D.Text = Mainform.MainSystem.Vreg[13].ToString();
                        if (txtV0E.Text != Mainform.MainSystem.Vreg[14].ToString())
                            txtV0E.Text = Mainform.MainSystem.Vreg[14].ToString();
                        if (txtV0F.Text != Mainform.MainSystem.Vreg[15].ToString())
                            txtV0F.Text = Mainform.MainSystem.Vreg[15].ToString();

                        if (txtRLP00.Text != Mainform.MainSystem.regRPL[0].ToString())
                            txtRLP00.Text = Mainform.MainSystem.regRPL[0].ToString();
                        if (txtRLP01.Text != Mainform.MainSystem.regRPL[1].ToString())
                            txtRLP01.Text = Mainform.MainSystem.regRPL[1].ToString();
                        if (txtRLP02.Text != Mainform.MainSystem.regRPL[2].ToString())
                            txtRLP02.Text = Mainform.MainSystem.regRPL[2].ToString();
                        if (txtRLP03.Text != Mainform.MainSystem.regRPL[3].ToString())
                            txtRLP03.Text = Mainform.MainSystem.regRPL[3].ToString();
                        if (txtRLP04.Text != Mainform.MainSystem.regRPL[4].ToString())
                            txtRLP04.Text = Mainform.MainSystem.regRPL[4].ToString();
                        if (txtRLP05.Text != Mainform.MainSystem.regRPL[5].ToString())
                            txtRLP05.Text = Mainform.MainSystem.regRPL[5].ToString();
                        if (txtRLP06.Text != Mainform.MainSystem.regRPL[6].ToString())
                            txtRLP06.Text = Mainform.MainSystem.regRPL[6].ToString();
                        if (txtRLP07.Text != Mainform.MainSystem.regRPL[7].ToString())
                            txtRLP07.Text = Mainform.MainSystem.regRPL[7].ToString();
                    }
                }
            }
        }

        private void cmdAdd_Click_1(object sender, EventArgs e)
        {
            using (frmBreakpoint frm = new frmBreakpoint())
            {
                frm.DB = this;
                frm.Addnew = true;
                frm.Mainform = this.Mainform;
                if (frm.ShowDialog() == DialogResult.OK)
                {
                    if (frm.BreapPointText != "")
                    lstBreakpoints.Items.Add(frm.BreapPointText);
                }

            }
        }

        private void cmdDelete_Click(object sender, EventArgs e)
        {
            if (lstBreakpoints.Items.Count > 0 && lstBreakpoints.SelectedIndex > -1 && Breakpoints.Count > 0)
            {
                Breakpoints.RemoveAt(lstBreakpoints.SelectedIndex);
                lstBreakpoints.Items.RemoveAt(lstBreakpoints.SelectedIndex);
            }
        }

        private void cmdEdit_Click_1(object sender, EventArgs e)
        {
            if (lstBreakpoints.Items.Count > 0 && lstBreakpoints.SelectedIndex > -1 && Breakpoints.Count > 0)
            {
                using (frmBreakpoint frm = new frmBreakpoint())
                {
                    frm.DB = this;
                    frm.Mainform = this.Mainform;
                    frm.txtaddress.Text = Breakpoints[lstBreakpoints.SelectedIndex].Address;
                    frm.chkread.Checked = Breakpoints[lstBreakpoints.SelectedIndex].Read;
                    frm.chkwrite.Checked = Breakpoints[lstBreakpoints.SelectedIndex].Write;
                    frm.chkexecute.Checked = Breakpoints[lstBreakpoints.SelectedIndex].Execute;
                    frm.SelectedIndex = lstBreakpoints.SelectedIndex;
                    if (frm.ShowDialog() == DialogResult.OK)
                    {
                        if (frm.BreapPointText != "")
                            lstBreakpoints.Items[lstBreakpoints.SelectedIndex] = frm.BreapPointText;
                    }
                }
            }
        }

        private void cmdSetPath_Click(object sender, EventArgs e)
        {
            using (SaveFileDialog sfd = new SaveFileDialog())
            {
                sfd.Filter = "log files (*.log)|*.log|All files (*.*)|*.*";
                if (sfd.ShowDialog() == System.Windows.Forms.DialogResult.OK)
                {
                    txtpath.Text = sfd.FileName;
                    chkLogCPU.Enabled = true;
                    chkIncludeRegisters.Enabled = true;
                }

            }
        }

        private void cmdStepOver_Click(object sender, EventArgs e)
        {
            Mainform.BreakPoint = true;
            Mainform.StepOver = true;
            Mainform.StepInto = true;
            Mainform.StepOut = false;
            Mainform.PauseEmulation = false;
        }

        private void cmCheats_Click(object sender, EventArgs e)
        {
            Mainform.CH.MainForm = this.Mainform;
            Mainform.CH.Show();
            Mainform.CH.Activate();
        }

        private void cmdPause_Click(object sender, EventArgs e)
        {
            Mainform.PauseEmulation ^= true;
        }

        private void cmdMemory_Click(object sender, EventArgs e)
        {
            Mainform.MV.Mainform = this.Mainform;
            Mainform.MV.Show();
            Mainform.MV.Activate();
        }
    }
}
